﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Media3D;

namespace LxCFD
{
    public struct Vector3d
    {
        public Vector3d(double x, double y, double z)
        {
            this.X = x;
            this.Y = y;
            this.Z = z;
        }
        public double X;
        public double Y;
        public double Z;
        public void AddToSelf(Vector3d v)
        {
            this.X += v.X;
            this.Y += v.Y;
            this.Z += v.Z;
        }
        public void MinusToSelf(Vector3d v)
        {
            this.X -= v.X;
            this.Y -= v.Y;
            this.Z -= v.Z;
        }
        public void MultiplyToSelf(double d)
        {
            X *= d;
            Y *= d;
            Z *= d;
        }
        public void Negate()
        {
            X = -X;
            Y = -Y;
            Z = -Z;
        }
        public double CalLengthSquared()
        {
            return Math.Pow(X, 2) + Math.Pow(Y, 2) + Math.Pow(Z, 2);
        }
        public double CalLength()
        {
            return Math.Sqrt(CalLengthSquared());
        }
        public override string ToString()
        {
            return X + "," + Y + "," + Z;
        }
        public  bool Is0()
        {
            return X == 0 && Y == 0 && Z == 0;
        }
        public Vector3D ToVector3D()
        {
            return new Vector3D(X, Y, Z);
        }
        public static Vector3d From2Point3D(Point3D startPoint, Point3D endPoint)
        {
            return new Vector3d(endPoint.X - startPoint.X, endPoint.Y - startPoint.Y, endPoint.Z - startPoint.Z);
        }
        public static bool TryParse(out Vector3d result, string inputString)
        {
            string t3 = inputString.Replace("，", ",");
            string[] s3 = t3.Split(',');
            result = new Vector3d();
            if (s3.Length == 3)
            {
                if (double.TryParse(s3[0], out result.X) && double.TryParse(s3[1], out result.Y) && double.TryParse(s3[2], out result.Z))
                {
                    return true;
                }
            }
            return false;
        }
        public static Vector3d operator +(Vector3d a, Vector3d b)
        {
            return new Vector3d(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
        }
        public static Vector3d operator -(Vector3d a, Vector3d b)
        {
            return new Vector3d(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
        }
        public static Vector3d operator -(Vector3d a)
        {
            return new Vector3d(-a.X, -a.Y, -a.Z);
        }
        public static Vector3d operator *(double d, Vector3d v)
        {
            return new Vector3d(v.X * d, v.Y * d, v.Z * d);
        }
        public static Vector3d operator *(Vector3d v, double d)
        {
            return new Vector3d(v.X * d, v.Y * d, v.Z * d);
        }
        public static double DotProduct(Vector3d a, Vector3d b)
        {
            return a.X * b.X + a.Y * b.Y + a.Z * b.Z;
        }
        public static Vector3d CrossProduct(Vector3d a, Vector3d b)
        {
            return new Vector3d(a.Y * b.Z - a.Z * b.Y, a.Z * b.X - a.X * b.Z, a.X * b.Y - a.Y * b.X);
        }
        public static Vector3d XXYYZZProduct(Vector3d a, Vector3d b)
        {
            return new Vector3d(a.X * b.X, a.Y * b.Y, a.Z * b.Z);
        }
        public static Point3D PointRotate(Point3D Old, Vector3D axis_1, Point3D pAxis, double Radian)//后续改为vector3d类型,不能删
        {//右手坐标系下，vector朝向你，逆时针旋转
            double c = Math.Cos(Radian);
            double c1 = 1 - c;
            double s = Math.Sin(Radian);
            double axy = axis_1.X * axis_1.Y;
            double ayz = axis_1.Y * axis_1.Z;
            double axz = axis_1.X * axis_1.Z;
            return new Point3D(
                (axis_1.X * axis_1.X * c1 + c) * (Old.X - pAxis.X) + (axy * c1 - axis_1.Z * s) * (Old.Y - pAxis.Y) + (axz * c1 + axis_1.Y * s) * (Old.Z - pAxis.Z) + pAxis.X,
                (axy * c1 + axis_1.Z * s) * (Old.X - pAxis.X) + (axis_1.Y * axis_1.Y * c1 + c) * (Old.Y - pAxis.Y) + (ayz * c1 - axis_1.X * s) * (Old.Z - pAxis.Z) + pAxis.Y,
                 (axz * c1 - axis_1.Y * s) * (Old.X - pAxis.X) + (ayz * c1 + axis_1.X * s) * (Old.Y - pAxis.Y) + (axis_1.Z * axis_1.Z * c1 + c) * (Old.Z - pAxis.Z) + pAxis.Z
                );
        }
        public static Vector3d PointToPlane(Vector3d pointOut, Vector3d vectorOfPlane, Vector3d pointInPlane)
        {
            double t = (vectorOfPlane.X * (pointOut.X - pointInPlane.X)
                + vectorOfPlane.Y * (pointOut.Y - pointInPlane.Y)
                + vectorOfPlane.Z * (pointOut.Z - pointInPlane.Z))
                / (vectorOfPlane.CalLengthSquared());
            return new Vector3d(pointOut.X - vectorOfPlane.X * t,
                pointOut.Y - vectorOfPlane.Y * t, pointOut.Z - vectorOfPlane.Z * t);
        }

        public static Vector3d VectorToPlane(Vector3d Vector, Vector3d vectorOfPlane)//矢量在平面上的投影
        {
            //Vector.MinusToSelf(DotProduct(Vector, vectorOfPlane) / vectorOfPlane.CalLengthSquared() * vectorOfPlane);
            //return Vector;
            return Vector - DotProduct(Vector, vectorOfPlane) / vectorOfPlane.CalLengthSquared() * vectorOfPlane;
        }

    }
}
//public void FindBound(ref Vector3d MinPosLog,ref Vector3d MaxPosLog)
//{
//    if (X < MinPosLog.X)
//    {
//        MinPosLog.X = X;
//    }else if(X>MaxPosLog.X)
//    {
//        MaxPosLog.X = X;
//    }
//    if (Y < MinPosLog.Y)
//    {
//        MinPosLog.Y = Y;
//    }
//    else if (Y > MaxPosLog.Y)
//    {
//        MaxPosLog.Y = Y;
//    }
//    if (Z < MinPosLog.Z)
//    {
//        MinPosLog.Z = Z;
//    }
//    else if (Z > MaxPosLog.Z)
//    {
//        MaxPosLog.Z = Z;
//    }
//}
//public static Vector3d FromVector3D(Vector3D vector3D)
//{
//    return new Vector3d(vector3D.X, vector3D.Y, vector3D.Z);
//}
//public static Vector3d operator -(Vector3D a, Vector3d b)
//{
//    return new Vector3d(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
//}
//public static double DotProduct(Vector3d a, Vector3D b)//兼容vector3D
//{
//    return a.X * b.X + a.Y * b.Y + a.Z * b.Z;
//}
//public static double DotProduct(Vector3D a, Vector3d b)//兼容vector3D
//{
//    return a.X * b.X + a.Y * b.Y + a.Z * b.Z;
//}
//public static Vector3d XXYYZZProduct(Vector3d a, Vector3D b)
//{
//    return new Vector3d(a.X * b.X, a.Y * b.Y, a.Z * b.Z);
//}
//public static Vector3d MultiplyDouble(Vector3D vector3d, double d)
//{            
//    return new Vector3d(vector3d.X * d, vector3d.Y * d, vector3d.Z * d);
//}
//public static Vector3d VectorToPlane(Vector3d Vector, Vector3D vectorOfPlane)//矢量在平面上的投影 兼容vector3D类型
//{

//    return Vector - ConverteFromVector3D(DotProduct(Vector, vectorOfPlane) / vectorOfPlane.LengthSquared * vectorOfPlane);
//}


//public static Vector3d ConverterFromPoint3D(Point3D point3D)
//{
//    return new Vector3d(point3D.X, point3D.Y, point3D.Z);
//}

//public static Vector3d MultiplyDouble(Vector3d vector3d, double d)
//{
//    return new Vector3d(vector3d.X * d, vector3d.Y * d, vector3d.Z * d);
//}